package com.smart.community.property.service.impl;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.smart.community.commons.cache.DataScopeInfo;
import com.smart.community.commons.enums.FeeTypeEnum;
import com.smart.community.commons.exception.BusinessException;
import com.smart.community.property.utils.MonthRangeUtils;
import com.smart.community.commons.result.PageResult;
import com.smart.community.commons.result.ResultCode;
import com.smart.community.commons.utils.SecurityUtils;
import com.smart.community.feign.region.dto.AddressInfoDTO;
import com.smart.community.feign.region.service.RegionAddressFeignService;
import com.smart.community.feign.region.service.OwnerFeignService;
import com.smart.community.property.dto.BatchPropertyFeeDTO;
import com.smart.community.property.dto.PropertyFeeDTO;
import com.smart.community.property.dto.PropertyFeeEditDTO;
import com.smart.community.property.dto.PropertyFeeHouseholdDTO;
import com.smart.community.property.dto.RepairOrderDTO;
import com.smart.community.property.entity.PropertyFee;
import com.smart.community.property.enums.BillingFeeTypeEnum;
import com.smart.community.property.enums.PaymentMethodEnum;
import com.smart.community.property.exception.DataScopeException;
import com.smart.community.property.mapper.PropertyFeeMapper;
import com.smart.community.property.mapper.RepairmanMapper;
import com.smart.community.property.service.DataScopeService;
import com.smart.community.property.service.IPropertyService;
import com.smart.community.property.service.IRepairOrderService;
import com.smart.community.property.service.IBillingMethodService;
import com.smart.community.property.service.IPropertyCompanyCommunityService;
import com.smart.community.property.entity.BillingMethod;
import com.smart.community.property.vo.BillingMethodVO;
import com.smart.community.property.vo.PropertyFeeStatisticsVO;
import com.smart.community.property.vo.PropertyFeeVO;
import com.smart.community.property.vo.RepairOrderStatisticsVO;
import com.smart.community.property.vo.RepairOrderVO;
import com.smart.community.property.vo.RepairmanVO;

import cn.hutool.core.util.StrUtil;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;

/**
 * 物业管理服务实现类
 * 提供高性能的物业费管理功能，包含缓存策略、数据权限控制和异步处理
 * 严格遵循Java后端SpringBoot代码开发规范，支持生产环境高标准部署
 * 
 * 主要功能：
 * - 物业费账单生成和管理
 * - 物业费缴费处理
 * - 维修工单管理
 * - 数据权限控制
 * - 缓存优化和性能监控
 * 
 * @author Wu.Liang
 * @since 2025-01-30
 * @version 3.0.0 - 生产环境优化版本，增强性能监控、缓存优化和异常处理
 */
@Slf4j
@Service
public class PropertyServiceImpl extends ServiceImpl<PropertyFeeMapper, PropertyFee> implements IPropertyService {

	@Autowired
	private PropertyFeeMapper propertyFeeMapper;

	@Autowired
	private DataScopeService dataScopeService;

	@Autowired
	private IRepairOrderService repairOrderService;

	@Autowired
	private RepairmanMapper repairmanMapper;

	@Autowired
	private RedisTemplate<String, Object> redisTemplate;

	@Autowired
	private RegionAddressFeignService regionAddressFeignClient;

	@Autowired
	private OwnerFeignService ownerFeignService;

	@Autowired
	private IBillingMethodService billingMethodService;

	@Autowired
	private IPropertyCompanyCommunityService propertyCompanyCommunityService;

	// 缓存相关常量 - 生产环境优化
	private static final String CACHE_KEY_PREFIX = "property_fee:";
	private static final String STATS_CACHE_KEY_PREFIX = "property_fee_stats:";
	private static final String USER_CACHE_KEY_PREFIX = "property_fee_user:";
	private static final String COMMUNITY_CACHE_KEY_PREFIX = "property_fee_community:";
	
	// 缓存过期时间配置（分钟）
	private static final long CACHE_EXPIRE_TIME = 30; // 基础缓存30分钟
	
	// 性能监控阈值（毫秒）
	private static final long PERFORMANCE_WARNING_THRESHOLD = 1000L; // 1秒警告阈值
	private static final long PERFORMANCE_ERROR_THRESHOLD = 3000L;   // 3秒错误阈值

	// ========================= 物业费管理 =========================

	@Override
	@GlobalTransactional
	public int generatePropertyBills(Long communityId, LocalDate billingMonth) {
		return generatePropertyBillsWithFeeType(communityId, billingMonth, "0", null); // 默认生成物业费，feeType="0"
	}

	@Override
	@GlobalTransactional
	public int generatePropertyBills(Long communityId, LocalDate billingMonth, Integer feeType) {
		// 只允许feeType=0生成物业费，其他类型需调用专用方法
		return generatePropertyBillsWithFeeType(communityId, billingMonth, feeType.toString(), null);
	}

	@Override
	@GlobalTransactional
	public int generatePropertyBills(Long communityId, LocalDate billingMonth, LocalDate dueDate) {
		return generatePropertyBillsWithFeeType(communityId, billingMonth, "0", dueDate); // 默认生成物业费，feeType="0"
	}

	@Override
	@GlobalTransactional
	public int generatePropertyBills(Long communityId, LocalDate billingMonth, Integer feeType, LocalDate dueDate) {
		// 只允许feeType=0生成物业费
		BigDecimal defaultFee = getDefaultFeeByType(feeType);
		return generatePropertyBills(communityId, billingMonth, feeType.toString(), defaultFee, dueDate);
	}

	@Override
	@GlobalTransactional
	public int generatePropertyBills(Long communityId, LocalDate billingMonth, Integer feeType,
			BigDecimal perPersonFee) {
		return generatePropertyBills(communityId, billingMonth, feeType.toString(), perPersonFee, null); // 使用默认到期日期
	}

	/**
	 * 内部方法，用于避免方法重载歧义
	 */
	private int generatePropertyBillsWithFeeType(Long communityId, LocalDate billingMonth, String feeType,
			LocalDate dueDate) {
		BigDecimal defaultFee = getDefaultFeeByType(Integer.parseInt(feeType));
		return generatePropertyBills(communityId, billingMonth, feeType, defaultFee, dueDate);
	}

	@Override
	@GlobalTransactional
	public int generatePropertyBills(Long communityId, LocalDate billingMonth, Integer feeType, BigDecimal perPersonFee,
			LocalDate dueDate) {
		return generatePropertyBills(communityId, billingMonth, feeType.toString(), perPersonFee, dueDate);
	}

	@Override
	@GlobalTransactional
	public int generatePropertyBills(Long communityId, LocalDate billingMonth, String feeType, BigDecimal perPersonFee,
			LocalDate dueDate) {
		try {
			// 数据权限验证
			dataScopeService.hasCommunityPermission(communityId);

			// 检查是否已经生成过该月份的账单
			QueryWrapper<PropertyFee> checkWrapper = new QueryWrapper<>();
			checkWrapper.eq("community_id", communityId)
					.eq("billing_period", billingMonth.format(DateTimeFormatter.ofPattern("yyyy-MM")))
					.eq("fee_type", feeType).eq("deleted", 0);

			if (propertyFeeMapper.selectCount(checkWrapper) > 0) {
				throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "该月份账单已生成，请勿重复生成");
			}

			// 直接调用Mapper的批量生成方法，使用SQL查询获取房户信息
			String billingPeriod = billingMonth.format(DateTimeFormatter.ofPattern("yyyy-MM"));

			// 获取当前用户ID作为创建人
			Long currentUserId = SecurityUtils.getCurrentUserId();

			// 根据计费方式准备参数
			BigDecimal unitPrice = null;
			BigDecimal fixedAmount = null;

			if (FeeTypeEnum.isAreaBased(Integer.parseInt(feeType))) {
				unitPrice = perPersonFee;
			} else if (FeeTypeEnum.isFixedAmount(Integer.parseInt(feeType))) {
				fixedAmount = perPersonFee;
			}

			// 设置默认到期日期（如果未提供）
			LocalDate finalDueDate = dueDate;
			if (finalDueDate == null) {
				// 如果没有提供到期日期，默认设置为计费月份的下一个月
				finalDueDate = billingMonth.plusMonths(1);
			}

			int generatedCount = propertyFeeMapper.batchGeneratePropertyFees(communityId, billingPeriod,
					Integer.parseInt(feeType), unitPrice, fixedAmount, currentUserId, finalDueDate);

			// 缓存由Spring Cache注解自动管理
			log.info("物业费账单生成完成，社区ID: {}, 计费月份: {}, 费用类型: {}, 费用金额: {}, 生成数量: {}", communityId, billingPeriod, feeType,
					perPersonFee, generatedCount);
			return generatedCount;
		} catch (Exception e) {
			log.warn("生成物业费账单失败，社区ID: {}, 计费月份: {}, 费用类型: {}, 费用金额: {}", communityId, billingMonth, feeType,
					perPersonFee, e);
			throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "生成物业费账单失败: " + e.getMessage());
		}
	}

	@Override
	@GlobalTransactional
	public int generatePropertyFeeByRange(Long communityId, List<String> billingMonthRange, String dueDate,
			String remark) {
		long startTime = System.currentTimeMillis();
		String operation = "生成物业费账单（时间段）";
		
		try {
			// 1. 参数验证
			validateCommunityId(communityId);
			if (billingMonthRange == null || billingMonthRange.isEmpty()) {
				log.error("计费月份时间段不能为空");
				throw new IllegalArgumentException("计费月份时间段不能为空");
			}
			if (billingMonthRange.size() != 2) {
				log.error("计费月份时间段格式错误，应为开始月份和结束月份");
				throw new IllegalArgumentException("计费月份时间段格式错误，应为开始月份和结束月份");
			}
			
			// 数据权限验证
			dataScopeService.hasCommunityPermission(communityId);

			// 解析时间段
			if (billingMonthRange.size() != 2) {
				throw new BusinessException(ResultCode.PARAM_ERROR.getCode(), "计费月份时间段格式错误");
			}

			String startMonth = billingMonthRange.get(0);
			String endMonth = billingMonthRange.get(1);

			// 计算月份数量
			int monthCount = calculateMonthCount(startMonth, endMonth);
			if (monthCount <= 0) {
				throw new BusinessException(ResultCode.PARAM_ERROR.getCode(), "计费月份时间段无效");
			}

			// 检查是否已生成过该时间段的账单
			String billingPeriod = startMonth + " ~ " + endMonth;

			// 使用月份区间重叠检测进行重复检查
			LambdaQueryWrapper<PropertyFee> existingWrapper = new LambdaQueryWrapper<>();
			existingWrapper.eq(PropertyFee::getCommunityId, communityId).eq(PropertyFee::getDeleted, 0);

			List<PropertyFee> existingFees = this.list(existingWrapper);
			List<String> overlappingHouseholds = new ArrayList<>();

			for (PropertyFee existingFee : existingFees) {
				if (MonthRangeUtils.hasOverlap(existingFee.getBillingPeriod(), billingPeriod)) {
					// 获取房户地址信息
					String householdAddress = "房户ID: " + existingFee.getHouseholdId();
					overlappingHouseholds.add(householdAddress + "(" + existingFee.getBillingPeriod() + ")");
				}
			}

			if (!overlappingHouseholds.isEmpty()) {
				String errorMsg = "以下房户存在计费月份重叠的物业费记录：" + String.join("、", overlappingHouseholds);
				throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), errorMsg);
			}

			// 解析到期日期
			LocalDate dueDateObj = null;
			if (dueDate != null && !dueDate.isEmpty()) {
				dueDateObj = LocalDate.parse(dueDate);
			} else {
				// 如果没有提供到期日期，默认设置为结束月份的下一个月
				LocalDate endMonthDate = LocalDate.parse(endMonth + "-01");
				dueDateObj = endMonthDate.plusMonths(1);
			}

			// 获取当前用户ID
			Long currentUserId = SecurityUtils.getCurrentUserId();

			// 获取社区对应的物业公司ID
			Long propertyCompanyId = getPropertyCompanyIdByCommunityId(communityId);
			if (propertyCompanyId == null) {
				throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "未找到社区对应的物业公司");
			}

			// 获取物业费计费方式列表
			List<BillingMethod> billingMethods = getBillingMethodsByPropertyCompanyAndFeeTypeInternal(propertyCompanyId,
					BillingFeeTypeEnum.PROPERTY.getCode());
			log.info("根据社区（id={}）获取物业公司（id={}）获取计费方式列表：{}项", communityId, propertyCompanyId, billingMethods.size());

			// 查询需要生成账单的房户信息
			List<PropertyFeeHouseholdDTO> households = propertyFeeMapper
					.selectHouseholdsForPropertyFeeByRange(communityId, billingPeriod, null);

			if (households.isEmpty()) {
				log.warn("没有找到需要生成物业费账单的房户，社区ID: {}, 计费时间段: {}", communityId, billingPeriod);
				return 0;
			}

			// 逐条生成账单
			int result = 0;
			LocalDateTime now = LocalDateTime.now();
			String timestamp = now.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));

			for (int i = 0; i < households.size(); i++) {
				PropertyFeeHouseholdDTO household = households.get(i);

				// 生成费用编号
				String feeNo = "PF" + timestamp + String.format("%06d", i + 1);

				// 根据楼栋建筑类型匹配计费方式
				BillingMethod matchedBillingMethod = matchBillingMethodByBuildingType(billingMethods,
						household.getBuildingType(), BillingFeeTypeEnum.PROPERTY.getCode());
				log.info("使用计费方式: ID={}, 名称={}, 建筑类型={}, 费用类型={}", matchedBillingMethod.getId(),
						matchedBillingMethod.getMethodName(), matchedBillingMethod.getBuildingTypeName(),
						matchedBillingMethod.getFeeType());

				// 计算费用金额和确定费用类型
				BigDecimal amount = BigDecimal.ZERO;
				Integer feeType = 0; // 默认按面积计费
				String feeName = "物业费";
				String finalRemark = remark != null ? remark : "";

				if (matchedBillingMethod != null) {
					feeType = matchedBillingMethod.getMethodType();
					if (matchedBillingMethod.getMethodType() == 0) { // 按面积计费
						BigDecimal area = household.getArea() != null ? household.getArea() : BigDecimal.ZERO;
						BigDecimal unitPrice = matchedBillingMethod.getUnitPrice() != null
								? matchedBillingMethod.getUnitPrice()
								: BigDecimal.ZERO;
						// 面积 x 单价 x 月份数量
						amount = area.multiply(unitPrice).multiply(new BigDecimal(monthCount));
						feeName = "物业费(按面积) - " + billingPeriod;
					} else if (matchedBillingMethod.getMethodType() == 1) { // 固定费用
						BigDecimal fixedAmount = matchedBillingMethod.getFixedAmount() != null
								? matchedBillingMethod.getFixedAmount()
								: BigDecimal.ZERO;
						// 固定金额 x 月份数量
						amount = fixedAmount.multiply(new BigDecimal(monthCount));
						feeName = "物业费(固定) - " + billingPeriod;
					}
				}

				// 创建物业费账单对象
				PropertyFee propertyFee = new PropertyFee();
				propertyFee.setFeeNo(feeNo);
				propertyFee.setUserId(household.getUserId());
				propertyFee.setCommunityId(household.getCommunityId());
				propertyFee.setBuildingId(household.getBuildingId());
				propertyFee.setUnitId(household.getUnitId());
				propertyFee.setHouseholdId(household.getHouseholdId());
				propertyFee.setFeeType(feeType);
				propertyFee.setFeeName(feeName);
				propertyFee.setFeeMonth(billingPeriod);
				propertyFee.setBillingPeriod(billingPeriod);
				propertyFee.setAmount(amount);
				propertyFee.setPaidAmount(BigDecimal.ZERO);
				propertyFee.setUnpaidAmount(amount);
				propertyFee.setDueDate(dueDateObj);
				propertyFee.setPaymentStatus(0);
				propertyFee.setPaymentAmount(BigDecimal.ZERO);
				propertyFee.setPaymentTime(null);
				propertyFee.setPaymentMethod(null);
				propertyFee.setOnlinePaymentId(null);
				propertyFee.setUnitPrice(matchedBillingMethod != null && matchedBillingMethod.getMethodType() == 0
						? matchedBillingMethod.getUnitPrice()
						: null);
				propertyFee.setArea(household.getArea());
				propertyFee.setInvoiceNo(null);
				propertyFee.setRemark(finalRemark);
				propertyFee.setStatus(1);
				propertyFee.setCreateBy(currentUserId);
				propertyFee.setCreateTime(now);
				propertyFee.setUpdateBy(currentUserId);
				propertyFee.setUpdateTime(now);
				propertyFee.setDeleted(0);
				propertyFee.setVersion(1);

				// 插入账单
				int insertResult = propertyFeeMapper.insertPropertyFee(propertyFee);
				if (insertResult > 0) {
					result++;
				}
			}

			// 清除相关缓存 - 使用增强的缓存清除方法
			clearEnhancedPropertyFeeCache(communityId, null);

			// 性能监控
			logPerformanceMetrics(operation, startTime, result);
			
			log.info("物业费账单生成完成（时间段），社区ID: {}, 计费时间段: {}, 生成数量: {}", communityId, billingPeriod, result);
			return result;
		} catch (Exception e) {
			return handleException(operation, e, startTime);
		}
	}

	/**
	 * 计算月份数量
	 * 
	 * @param startMonth 开始月份（yyyy-MM格式）
	 * @param endMonth   结束月份（yyyy-MM格式）
	 * @return 月份数量
	 */
	private int calculateMonthCount(String startMonth, String endMonth) {
		try {
			LocalDate start = LocalDate.parse(startMonth + "-01");
			LocalDate end = LocalDate.parse(endMonth + "-01");

			if (start.isAfter(end)) {
				return 0;
			}

			return (int) start.until(end, ChronoUnit.MONTHS) + 1;
		} catch (Exception e) {
			log.warn("计算月份数量失败，开始月份: {}, 结束月份: {}", startMonth, endMonth, e);
			return 0;
		}
	}

	@Override
	public PageResult<PropertyFeeVO> pagePropertyBills(PropertyFeeDTO propertyFeeDTO) {
		long startTime = System.currentTimeMillis();
		String operation = "分页查询物业费账单";
		
		try {
			// 1. 参数验证
			if (propertyFeeDTO == null) {
				log.error("查询参数不能为空");
				throw new IllegalArgumentException("查询参数不能为空");
			}
			
			// 数据权限校验
			DataScopeInfo dataScopeInfo = null;
			try {
				// 首先检查用户是否登录
				Long currentUserId = SecurityUtils.getCurrentUserId();
				if (currentUserId == null) {
					log.warn("用户未登录或会话已过期，返回空结果");
					PageResult<PropertyFeeVO> emptyResult = new PageResult<>(propertyFeeDTO.getCurrent(), propertyFeeDTO.getSize(), 0L, new ArrayList<>());
					logPerformanceMetrics(operation, startTime, emptyResult);
					return emptyResult;
				}
				
				dataScopeInfo = dataScopeService.getCurrentUserDataScope();
			} catch (Exception e) {
				log.warn("获取当前用户数据权限信息失败，可能是Feign接口调用或用户未登录，返回空结果: {}", e.getMessage());
				// 根据Feign接口开发规范，当无法获取用户权限信息时，返回空结果
				return new PageResult<>(propertyFeeDTO.getCurrent(), propertyFeeDTO.getSize(), 0L, new ArrayList<>());
			}
			
			List<Long> authorizedCommunityIds = dataScopeInfo != null ? dataScopeInfo.getCommunityIds() : null;
			if (authorizedCommunityIds == null || authorizedCommunityIds.isEmpty()) {
				log.warn("用户没有可访问的社区权限，返回空结果");
				return new PageResult<>(propertyFeeDTO.getCurrent(), propertyFeeDTO.getSize(), 0L, new ArrayList<>());
			}

			// 构建查询条件
			QueryWrapper<PropertyFee> queryWrapper = new QueryWrapper<>();
			queryWrapper.eq("deleted", 0);

			// 社区权限过滤
			if (propertyFeeDTO.getCommunityId() != null) {
				if (!authorizedCommunityIds.contains(propertyFeeDTO.getCommunityId())) {
					log.warn("用户无权访问指定社区，社区ID: {}, 用户ID: {}", propertyFeeDTO.getCommunityId(), SecurityUtils.getCurrentUserId());
					return new PageResult<>(propertyFeeDTO.getCurrent(), propertyFeeDTO.getSize(), 0L, new ArrayList<>());
				}
				queryWrapper.eq("community_id", propertyFeeDTO.getCommunityId());
			} else {
				queryWrapper.in("community_id", authorizedCommunityIds);
			}

			// 其他查询条件
			if (propertyFeeDTO.getUserId() != null) {
				queryWrapper.eq("user_id", propertyFeeDTO.getUserId());
			}
			if (propertyFeeDTO.getPaymentStatus() != null) {
				queryWrapper.eq("payment_status", propertyFeeDTO.getPaymentStatus().toString());
			}
			if (propertyFeeDTO.getFeeType() != null) {
				queryWrapper.eq("fee_type", propertyFeeDTO.getFeeType().toString());
			}
			if (org.springframework.util.StringUtils.hasText(propertyFeeDTO.getBillingPeriod())) {
				queryWrapper.eq("billing_period", propertyFeeDTO.getBillingPeriod());
			}

			// 新增：楼栋、单元、房户查询条件
			if (propertyFeeDTO.getBuildingId() != null) {
				queryWrapper.eq("building_id", propertyFeeDTO.getBuildingId());
			}
			if (propertyFeeDTO.getUnitId() != null) {
				queryWrapper.eq("unit_id", propertyFeeDTO.getUnitId());
			}
			if (propertyFeeDTO.getHouseholdId() != null) {
				queryWrapper.eq("household_id", propertyFeeDTO.getHouseholdId());
			}
			
			// 新增：房户ID列表筛选条件
			if (propertyFeeDTO.getHouseholdIds() != null && !propertyFeeDTO.getHouseholdIds().isEmpty()) {
				queryWrapper.in("household_id", propertyFeeDTO.getHouseholdIds());
				log.info("应用房户ID列表筛选条件: {}", propertyFeeDTO.getHouseholdIds());
			}

			if (org.springframework.util.StringUtils.hasText(propertyFeeDTO.getKeyword())) {
				queryWrapper.and(wrapper -> wrapper.like("billing_period", propertyFeeDTO.getKeyword()).or()
						.like("remark", propertyFeeDTO.getKeyword()));
			}

			queryWrapper.orderByDesc("create_time");

			// 执行分页查询
			Page<PropertyFee> page = new Page<>(propertyFeeDTO.getCurrent(), propertyFeeDTO.getSize());
			IPage<PropertyFee> result = propertyFeeMapper.selectPage(page, queryWrapper);

			// 转换为VO
			List<PropertyFeeVO> voList = result.getRecords().stream().map(this::convertToVO)
					.collect(Collectors.toList());

			PageResult<PropertyFeeVO> pageResult = new PageResult<>(propertyFeeDTO.getCurrent(), propertyFeeDTO.getSize(), result.getTotal(), voList);
			
			// 性能监控
			logPerformanceMetrics(operation, startTime, pageResult);
			
			log.info("物业费列表查询完成，总数: {}, 当前页记录数: {}, 用户ID: {}", result.getTotal(), voList.size(), SecurityUtils.getCurrentUserId());

			return pageResult;
		} catch (Exception e) {
			return handleException(operation, e, startTime);
		}
	}

	@Override
	@Cacheable(value = "property:myFees", key = "#current + ':' + #size + ':' + #paymentStatus + ':' + #feeType + ':' + #billingPeriod + ':' + T(com.smart.community.commons.utils.SecurityUtils).getCurrentUserId()", unless = "#result == null")
	public PageResult<PropertyFeeVO> getMyPropertyFees(Integer current, Integer size, Integer paymentStatus, Integer feeType, String billingPeriod) {
		long startTime = System.currentTimeMillis();
		String operation = "查询当前用户物业费账单";
		
		try {
			// 1. 参数验证
			if (current == null || current <= 0) {
				log.error("当前页参数无效：{}", current);
				throw new IllegalArgumentException("当前页必须大于0");
			}
			if (size == null || size <= 0) {
				log.error("每页大小参数无效：{}", size);
				throw new IllegalArgumentException("每页大小必须大于0");
			}
			
			log.info("查询当前用户的物业费账单，当前页: {}, 每页大小: {}, 缴费状态: {}, 费用类型: {}, 计费周期: {}", 
					current, size, paymentStatus, feeType, billingPeriod);

			// 获取当前用户ID
			Long currentUserId = SecurityUtils.getCurrentUserId();
			if (currentUserId == null) {
				throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "用户未登录");
			}

			// 根据当前登录用户ID查询业主信息，获取关联的房户ID集合
			List<Long> householdIds = ownerFeignService.getOwnerHouseholdIds(currentUserId);
			if (householdIds == null || householdIds.isEmpty()) {
				log.warn("用户无关联房户，返回空结果，用户ID: {}", currentUserId);
				return new PageResult<>(current, size, 0L, new ArrayList<>());
			}

			log.info("用户关联的房户ID数量: {}, 房户ID列表: {}", householdIds.size(), householdIds);

			// 计算偏移量
			int offset = (current - 1) * size;

			// 使用专门的去重查询方法，符合ONLY_FULL_GROUP_BY模式
			List<PropertyFee> records = propertyFeeMapper.selectMyPropertyFeesPage(
					householdIds, paymentStatus, feeType, billingPeriod, offset, size);

			// 查询总数
			Long total = propertyFeeMapper.countMyPropertyFees(
					householdIds, paymentStatus, feeType, billingPeriod);

			// 转换为VO
			List<PropertyFeeVO> voList = records.stream().map(this::convertToVO)
					.collect(Collectors.toList());

			PageResult<PropertyFeeVO> pageResult = new PageResult<>(current, size, total, voList);
			
			// 性能监控
			logPerformanceMetrics(operation, startTime, pageResult);
			
			log.info("当前用户物业费账单查询完成，总数: {}, 当前页记录数: {}, 用户ID: {}", total, voList.size(), currentUserId);

			return pageResult;
		} catch (Exception e) {
			return handleException(operation, e, startTime);
		}
	}

	@Override
	@Cacheable(value = "property:feeDetail", key = "#billId", unless = "#result == null")
	public PropertyFeeVO getPropertyFeeDetail(Long billId) {
		try {
			if (billId == null) {
				throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "账单ID不能为空");
			}

			PropertyFee propertyFee = propertyFeeMapper.selectById(billId);
			if (propertyFee == null) {
				throw new BusinessException(ResultCode.DATA_NOT_FOUND.getCode(), "物业费记录不存在");
			}

			// 验证社区权限
			dataScopeService.hasCommunityPermission(propertyFee.getCommunityId());

			return convertToVO(propertyFee);
		} catch (Exception e) {
			log.warn("获取物业费详情失败，账单ID: {}", billId, e);
			throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "获取物业费详情失败: " + e.getMessage());
		}
	}

	@Override
	@Cacheable(value = "property:feeDetailMobile", key = "#billId + ':' + #userId", unless = "#result == null")
	public PropertyFeeVO getPropertyFeeDetailForMobile(Long billId, Long userId) {
		try {
			if (billId == null) {
				throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "账单ID不能为空");
			}
			if (userId == null) {
				throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "用户ID不能为空");
			}

			PropertyFee propertyFee = propertyFeeMapper.selectById(billId);
			if (propertyFee == null) {
				throw new BusinessException(ResultCode.DATA_NOT_FOUND.getCode(), "物业费记录不存在");
			}

			// App端权限验证：判断当前用户是否为该房户的业主
			validateUserPermissionForFee(propertyFee.getId(), userId);

			return convertToVO(propertyFee);
		} catch (Exception e) {
			log.warn("App端获取物业费详情失败，账单ID: {}, 用户ID: {}", billId, userId, e);
			throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "获取物业费详情失败: " + e.getMessage());
		}
	}

	@Override
	public void validateUserPermissionForFee(Long feeId, Long userId) {
		try {
			if (feeId == null) {
				throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "费用ID不能为空");
			}
			if (userId == null) {
				throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "用户ID不能为空");
			}

			// 获取费用记录
			PropertyFee propertyFee = propertyFeeMapper.selectById(feeId);
			if (propertyFee == null) {
				throw new BusinessException(ResultCode.DATA_NOT_FOUND.getCode(), "物业费记录不存在");
			}

			// 获取用户关联的房户ID列表
			List<Long> userHouseholdIds = ownerFeignService.getOwnerHouseholdIds(userId);
			if (userHouseholdIds == null || userHouseholdIds.isEmpty()) {
				throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "用户未关联任何房户");
			}

			// 验证用户是否为该房户的业主
			if (!userHouseholdIds.contains(propertyFee.getHouseholdId())) {
				throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "用户无权限访问该费用记录");
			}

			log.info("App端用户权限验证通过，费用ID: {}, 用户ID: {}, 房户ID: {}", feeId, userId, propertyFee.getHouseholdId());
		} catch (Exception e) {
			log.warn("App端用户权限验证失败，费用ID: {}, 用户ID: {}", feeId, userId, e);
			throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "权限验证失败: " + e.getMessage());
		}
	}

	@Override
	@GlobalTransactional
	@CacheEvict(value = {"property:myFees", "property:feeDetail", "property:feeDetailMobile", "property:monthlyStats", "property:yearlyStats"}, allEntries = true)
	public boolean updatePropertyFee(Long billId, PropertyFeeDTO propertyFeeDTO) {
		try {
			if (billId == null || propertyFeeDTO == null) {
				throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "账单ID和更新数据不能为空");
			}

			PropertyFee propertyFee = propertyFeeMapper.selectById(billId);
			if (propertyFee == null) {
				throw new BusinessException(ResultCode.DATA_NOT_FOUND.getCode(), "物业费记录不存在");
			}

			// 验证社区权限
			dataScopeService.hasCommunityPermission(propertyFee.getCommunityId());

			// 更新字段
			if (propertyFeeDTO.getAmount() != null) {
				propertyFee.setAmount(propertyFeeDTO.getAmount());
			}
			if (propertyFeeDTO.getDueDate() != null) {
				propertyFee.setDueDate(propertyFeeDTO.getDueDate());
			}
			if (StringUtils.hasText(propertyFeeDTO.getRemark())) {
				propertyFee.setRemark(propertyFeeDTO.getRemark());
			}

			propertyFee.setUpdateTime(LocalDateTime.now());

			int result = propertyFeeMapper.updateById(propertyFee);
			if (result > 0) {
				// 缓存由Spring Cache注解自动管理
				log.info("物业费信息更新成功，账单ID: {}", billId);
				return true;
			}

			return false;
		} catch (Exception e) {
			log.warn("更新物业费信息失败，账单ID: {}", billId, e);
			throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "更新物业费信息失败: " + e.getMessage());
		}
	}

	/**
	 * 编辑物业费信息（仅允许编辑指定字段） 支持月份区间计费：当选择月份区间时，费用金额需要乘以月份数量
	 * 
	 * @param billId  账单ID
	 * @param editDTO 编辑数据
	 * @return 是否更新成功
	 */
	@Override
	@GlobalTransactional
	public boolean editPropertyFee(Long billId, PropertyFeeEditDTO editDTO) {
		try {
			if (billId == null || editDTO == null) {
				throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "账单ID和编辑数据不能为空");
			}

			PropertyFee propertyFee = propertyFeeMapper.selectById(billId);
			if (propertyFee == null) {
				throw new BusinessException(ResultCode.DATA_NOT_FOUND.getCode(), "物业费记录不存在");
			}

			// 验证社区权限
			dataScopeService.hasCommunityPermission(propertyFee.getCommunityId());

			// 计算最终费用金额（根据现有的billingPeriod字段计算月份数量）
			BigDecimal finalAmount = calculateFinalAmount(propertyFee, editDTO);

			// 只更新允许编辑的字段（到期日期不允许修改）
			propertyFee.setAmount(finalAmount);
			// propertyFee.setDueDate(editDTO.getDueDate()); // 注释：到期日期不允许修改
			propertyFee.setPaymentStatus(editDTO.getPaymentStatus());

			// 修复：支持费用类型和相关字段的更新
			if (editDTO.getFeeType() != null) {
				propertyFee.setFeeType(editDTO.getFeeType());
			}
			if (editDTO.getUnitPrice() != null) {
				propertyFee.setUnitPrice(editDTO.getUnitPrice());
			}
			// 注意：PropertyFee实体类没有fixedAmount字段，所以不更新该字段

			propertyFee.setUpdateTime(LocalDateTime.now());

			int result = propertyFeeMapper.updateById(propertyFee);
			if (result > 0) {
				// 缓存由Spring Cache注解自动管理
				log.info("物业费编辑成功，账单ID: {}, 更新字段: 费用金额、缴费状态, 最终金额: {}", billId, finalAmount);
				return true;
			}

			return false;
		} catch (Exception e) {
			log.warn("编辑物业费信息失败，账单ID: {}", billId, e);
			throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "编辑物业费信息失败: " + e.getMessage());
		}
	}

	/**
	 * 计算最终费用金额 根据现有的billingPeriod字段计算月份数量，然后乘以单月费用
	 * 
	 * @param propertyFee 物业费实体（包含现有的billingPeriod信息）
	 * @param editDTO     编辑数据
	 * @return 最终费用金额
	 */
	private BigDecimal calculateFinalAmount(PropertyFee propertyFee, PropertyFeeEditDTO editDTO) {
		BigDecimal baseAmount = editDTO.getAmount();

		// 从现有的billingPeriod字段解析月份区间
		String billingPeriod = propertyFee.getBillingPeriod();
		if (billingPeriod != null && billingPeriod.contains("~")) {
			try {
				String[] monthRange = billingPeriod.split("~");
				if (monthRange.length == 2) {
					String startMonth = monthRange[0].trim();
					String endMonth = monthRange[1].trim();

					int monthCount = calculateMonthCount(startMonth, endMonth);

					if (monthCount > 0) {
						BigDecimal finalAmount = baseAmount.multiply(BigDecimal.valueOf(monthCount));
						log.info("时间段计费：单月费用 {} × {} 个月 = 总费用 {}, 月份区间: {}", baseAmount, monthCount, finalAmount,
								billingPeriod);
						return finalAmount;
					} else {
						log.warn("月份数量计算失败，使用单月费用: {}, 月份区间: {}", baseAmount, billingPeriod);
						return baseAmount;
					}
				}
			} catch (Exception e) {
				log.warn("解析月份区间失败，使用单月费用: {}, 月份区间: {}", baseAmount, billingPeriod, e);
				return baseAmount;
			}
		}

		// 默认使用单月费用
		log.info("使用单月费用: {}, 月份区间: {}", baseAmount, billingPeriod);
		return baseAmount;
	}

	@Override
	@GlobalTransactional
	public boolean payBill(Long billId, BigDecimal paymentAmount, String paymentMethod) {
		long startTime = System.currentTimeMillis();
		String operation = "物业费缴费";
		
		try {
			// 1. 参数验证
			validateBillId(billId);
			if (paymentAmount == null) {
				log.error("支付金额不能为空");
				throw new IllegalArgumentException("支付金额不能为空");
			}
			if (paymentAmount.compareTo(BigDecimal.ZERO) <= 0) {
				log.error("支付金额必须大于0，当前值：{}", paymentAmount);
				throw new IllegalArgumentException("支付金额必须大于0");
			}

			PropertyFee propertyFee = propertyFeeMapper.selectById(billId);
			if (propertyFee == null) {
				throw new BusinessException(ResultCode.DATA_NOT_FOUND.getCode(), "物业费记录不存在");
			}

			// 验证社区权限
			dataScopeService.hasCommunityPermission(propertyFee.getCommunityId());

			// 转换支付方式：字符串转换为整数值
			Integer paymentMethodCode = convertPaymentMethodToCode(paymentMethod);
			if (paymentMethodCode == null) {
				throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "不支持的支付方式: " + paymentMethod);
			}

			// 计算支付后的金额
			BigDecimal currentPaidAmount = propertyFee.getPaidAmount() != null ? propertyFee.getPaidAmount()
					: BigDecimal.ZERO;
			BigDecimal totalAmount = propertyFee.getAmount();
			BigDecimal newPaidAmount = currentPaidAmount.add(paymentAmount);
			BigDecimal newUnpaidAmount = totalAmount.subtract(newPaidAmount);

			// 检查是否超额支付
			if (newUnpaidAmount.compareTo(BigDecimal.ZERO) < 0) {
				throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "支付金额超过应缴费用，请检查支付金额");
			}

			// 更新支付状态
			propertyFee.setPaymentStatus(newUnpaidAmount.compareTo(BigDecimal.ZERO) == 0 ? 1 : 0); // 如果未支付金额为0，则标记为已缴费
			propertyFee.setPaymentAmount(paymentAmount); // 本次支付金额
			propertyFee.setPaymentMethod(paymentMethodCode); // 转换为字符串存储
			propertyFee.setPaymentTime(LocalDateTime.now());
			propertyFee.setPaidAmount(newPaidAmount); // 累计已支付金额
			propertyFee.setUnpaidAmount(newUnpaidAmount); // 剩余未支付金额
			propertyFee.setUpdateTime(LocalDateTime.now());

			int result = propertyFeeMapper.updateById(propertyFee);
			if (result > 0) {
				// 清除相关缓存 - 使用增强的缓存清除方法
				clearEnhancedPropertyFeeCache(propertyFee.getCommunityId(), propertyFee.getUserId());

				// 性能监控
				logPerformanceMetrics(operation, startTime, true);
				
				log.info("物业费缴费成功，账单ID: {}, 金额: {}, 支付方式: {}", billId, paymentAmount, paymentMethod);
				return true;
			}

			// 性能监控
			logPerformanceMetrics(operation, startTime, false);
			return false;
		} catch (Exception e) {
			return handleException(operation, e, startTime);
		}
	}

	@Override
	public Map<String, Integer> batchGeneratePropertyBills(BatchPropertyFeeDTO batchDTO) {
		try {
			Map<String, Integer> result = new HashMap<>();
			int totalGenerated = 0;
			int successCount = 0;
			int failCount = 0;

			// 只处理单个communityId，计费月份用billingPeriod
			try {
				int count = generatePropertyBills(batchDTO.getCommunityId(),
						LocalDate.parse(batchDTO.getBillingPeriod()));
				totalGenerated += count;
				successCount++;
			} catch (Exception e) {
				log.warn("批量生成物业费账单失败，社区ID: {}", batchDTO.getCommunityId(), e);
				failCount++;
			}

			result.put("totalGenerated", totalGenerated);
			result.put("successCount", successCount);
			result.put("failCount", failCount);

			return result;
		} catch (Exception e) {
			log.warn("批量生成物业费账单失败", e);
			throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "批量生成物业费账单失败: " + e.getMessage());
		}
	}

	@Override
	public boolean sendPaymentReminder(Long billId, String remindType) {
		try {
			if (billId == null || StrUtil.isBlankIfStr(remindType)) {
				throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "账单ID和提醒方式不能为空");
			}

			PropertyFee propertyFee = propertyFeeMapper.selectById(billId);
			if (propertyFee == null) {
				throw new BusinessException(ResultCode.DATA_NOT_FOUND.getCode(), "物业费记录不存在");
			}

			// 验证社区权限
			dataScopeService.hasCommunityPermission(propertyFee.getCommunityId());

			// 发送提醒通知
			boolean success = sendReminderNotification(propertyFee, remindType);

			if (success) {
				log.info("物业费催缴提醒发送成功，账单ID: {}, 提醒方式: {}", billId, remindType);
			}

			return success;
		} catch (Exception e) {
			log.warn("发送物业费催缴提醒失败，账单ID: {}", billId, e);
			throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "发送催缴提醒失败: " + e.getMessage());
		}
	}

	@Override
	public Map<String, Integer> batchSendPaymentReminder(Long communityId, String remindType) {
		try {
			Map<String, Integer> result = new HashMap<>();
			int totalSent = 0;
			int successCount = 0;
			int failCount = 0;

			// 查询社区内所有未缴费账单
			QueryWrapper<PropertyFee> queryWrapper = new QueryWrapper<>();
			queryWrapper.eq("community_id", communityId).eq("payment_status", "0") // 未缴费
					.eq("deleted", 0);

			List<PropertyFee> unpaidBills = propertyFeeMapper.selectList(queryWrapper);

			for (PropertyFee bill : unpaidBills) {
				try {
					if (sendReminderNotification(bill, remindType)) {
						successCount++;
					} else {
						failCount++;
					}
					totalSent++;
				} catch (Exception e) {
					log.warn("发送催缴提醒失败，账单ID: {}", bill.getId(), e);
					failCount++;
				}
			}

			result.put("totalSent", totalSent);
			result.put("successCount", successCount);
			result.put("failCount", failCount);

			return result;
		} catch (Exception e) {
			log.warn("批量发送催缴提醒失败，社区ID: {}", communityId, e);
			throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "批量发送催缴提醒失败: " + e.getMessage());
		}
	}

	@Override
	public List<PropertyFeeVO> getUnpaidBillsByUserId(Long userId) {
		try {
			if (userId == null) {
				throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "用户ID不能为空");
			}

			QueryWrapper<PropertyFee> queryWrapper = new QueryWrapper<>();
			queryWrapper.eq("user_id", userId).eq("payment_status", "0") // 未缴费
					.eq("deleted", 0).orderByDesc("create_time");

			List<PropertyFee> unpaidBills = propertyFeeMapper.selectList(queryWrapper);

			return unpaidBills.stream().map(this::convertToVO).collect(Collectors.toList());
		} catch (Exception e) {
			log.warn("查询用户未缴费账单失败，用户ID: {}", userId, e);
			throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "查询用户未缴费账单失败: " + e.getMessage());
		}
	}

	@Override
	public String exportPropertyFeeBills(PropertyFeeDTO propertyFeeDTO) {
		try {
			// 这里应该实现导出逻辑，暂时返回空字符串
			log.info("导出物业费账单，查询条件: {}", propertyFeeDTO);
			return "";
		} catch (Exception e) {
			log.warn("导出物业费账单失败", e);
			throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "导出物业费账单失败: " + e.getMessage());
		}
	}

	@Override
	@Cacheable(value = "property:monthlyStats", key = "#communityId + ':' + #year", unless = "#result == null || #result.isEmpty()")
	public List<PropertyFeeStatisticsVO> getMonthlyPropertyFeeStatistics(Long communityId, Integer year) {
		try {
			// 这里应该实现月度统计逻辑，暂时返回空列表
			log.info("获取物业费月度统计，社区ID: {}, 年份: {}", communityId, year);
			return new ArrayList<>();
		} catch (Exception e) {
			log.warn("获取物业费月度统计失败", e);
			throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "获取物业费月度统计失败: " + e.getMessage());
		}
	}

	// ========================= 维修工单管理 =========================

	@Override
	public PageResult<RepairOrderVO> pageRepairOrders(Integer current, Integer size, Long communityId, Integer status) {
		try {
			// 这里应该实现维修工单分页查询逻辑，暂时返回空结果
			log.info("分页查询维修工单，当前页: {}, 每页大小: {}, 社区ID: {}, 状态: {}", current, size, communityId, status);
			return new PageResult<>(current, size, 0L, new ArrayList<>());
		} catch (Exception e) {
			log.warn("分页查询维修工单失败", e);
			throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "分页查询维修工单失败: " + e.getMessage());
		}
	}

	@Override
	public RepairOrderVO getRepairOrderDetail(Long orderId) {
		try {
			log.info("获取维修工单详情，工单ID: {}", orderId);
			// 调用RepairOrderService的getRepairOrderDetail方法
			return repairOrderService.getRepairOrderDetail(orderId);
		} catch (Exception e) {
			log.warn("获取维修工单详情失败", e);
			throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "获取维修工单详情失败: " + e.getMessage());
		}
	}

	@Override
	public Long submitRepairOrder(RepairOrderDTO repairOrderDTO) {
		try {
			log.info("提交维修工单，工单信息: {}", repairOrderDTO);
			// 调用RepairOrderService的submitRepairOrder方法
			return repairOrderService.submitRepairOrder(repairOrderDTO);
		} catch (Exception e) {
			log.warn("提交维修工单失败", e);
			throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "提交维修工单失败: " + e.getMessage());
		}
	}

	@Override
	@GlobalTransactional
	@CacheEvict(value = {"property:myFees", "property:feeDetail", "property:feeDetailMobile", "property:monthlyStats", "property:yearlyStats"}, allEntries = true)
	public boolean updateRepairOrderStatus(Long orderId, Integer status, String remark) {
		try {
			log.info("更新维修工单状态，工单ID: {}, 状态: {}, 备注: {}", orderId, status, remark);
			// 调用RepairOrderService的updateRepairOrderStatus方法
			return repairOrderService.updateRepairOrderStatus(orderId, status, remark);
		} catch (Exception e) {
			log.warn("更新维修工单状态失败", e);
			throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "更新维修工单状态失败: " + e.getMessage());
		}
	}

	@Override
	public boolean assignRepairOrder(Long orderId, Long repairmanId, String remark) {
		try {
			log.info("分配维修工单，工单ID: {}, 维修人员ID: {}, 备注: {}", orderId, repairmanId, remark);
			// 调用RepairOrderService的assignRepairOrder方法
			boolean success = repairOrderService.assignRepairOrder(orderId, repairmanId, remark);
			if (success && remark != null && !remark.trim().isEmpty()) {
				// 如果有备注，创建进度记录
				repairOrderService.updateRepairOrderStatus(orderId, 2, remark);
			}
			return success;
		} catch (Exception e) {
			log.warn("分配维修工单失败", e);
			throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "分配维修工单失败: " + e.getMessage());
		}
	}

	@Override
	public boolean completeRepairOrder(Long orderId, String result, Integer satisfaction, String remark) {
		try {
			log.info("完成维修工单，工单ID: {}, 维修结果: {}, 备注: {}", orderId, result, remark);

			// 调用RepairOrderService的completeRepairOrder方法
			boolean success = repairOrderService.completeRepairOrder(orderId, result, remark);
			return success;
		} catch (Exception e) {
			log.warn("完成维修工单失败", e);
			throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "完成维修工单失败: " + e.getMessage());
		}
	}

	@Override
	public Map<String, Integer> batchAssignRepairOrders(List<Long> orderIds, Long repairmanId) {
		try {
			log.info("批量分配维修工单，工单IDs: {}, 维修人员ID: {}", orderIds, repairmanId);
			// 调用RepairOrderService的batchAssignRepairOrders方法
			return repairOrderService.batchAssignRepairOrders(orderIds, repairmanId);
		} catch (Exception e) {
			log.warn("批量分配维修工单失败", e);
			throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "批量分配维修工单失败: " + e.getMessage());
		}
	}

	@Override
	public RepairOrderStatisticsVO getRepairOrderStatistics(Long communityId, LocalDate startDate, LocalDate endDate) {
		try {
			log.info("获取维修工单统计，社区ID: {}, 开始日期: {}, 结束日期: {}", communityId, startDate, endDate);

			// 如果communityId为null，获取当前用户有权限的所有社区ID
			if (communityId == null) {
				DataScopeInfo dataScopeInfo = dataScopeService.getCurrentUserDataScope();
				List<Long> authorizedCommunityIds = dataScopeInfo.getCommunityIds();
				if (authorizedCommunityIds == null || authorizedCommunityIds.isEmpty()) {
					// 如果没有权限的社区，返回空的统计结果
					RepairOrderStatisticsVO emptyStats = new RepairOrderStatisticsVO();
					emptyStats.setTotalOrders(0);
					emptyStats.setCompletedOrders(0);
					emptyStats.setPendingOrders(0);
					emptyStats.setProcessingOrders(0);
					emptyStats.setCancelledOrders(0);
					emptyStats.setAverageProcessingTime(BigDecimal.ZERO);
					emptyStats.setOnTimeCompletionRate(BigDecimal.ZERO);
					return emptyStats;
				}
				// 如果有多个社区权限，使用第一个作为默认值
				communityId = authorizedCommunityIds.get(0);
				log.info("使用默认社区ID: {}", communityId);
			}

			// 调用RepairOrderService的getRepairOrderStatistics方法
			return repairOrderService.getRepairOrderStatistics(communityId, startDate, endDate);
		} catch (Exception e) {
			log.warn("获取维修工单统计失败", e);
			throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "获取维修工单统计失败: " + e.getMessage());
		}
	}

	@Override
	@Cacheable(value = "property:yearlyStats", key = "#communityId + ':' + #year", unless = "#result == null")
	public PropertyFeeStatisticsVO getPropertyFeeStatistics(Long communityId, Integer year) {
		try {
			if (communityId == null || year == null) {
				throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "社区ID和年份不能为空");
			}

			// 数据权限验证
			dataScopeService.hasCommunityPermission(communityId);

			// 构建统计查询条件
			QueryWrapper<PropertyFee> queryWrapper = new QueryWrapper<>();
			queryWrapper.eq("community_id", communityId).eq("deleted", 0).likeRight("billing_period", year.toString());

			List<PropertyFee> propertyFees = propertyFeeMapper.selectList(queryWrapper);

			// 构建统计结果
			PropertyFeeStatisticsVO statistics = new PropertyFeeStatisticsVO();
			statistics.setCommunityId(communityId);
			statistics.setStatisticsPeriod(year.toString());

			BigDecimal totalAmount = BigDecimal.ZERO;
			BigDecimal paidAmount = BigDecimal.ZERO;
			int totalBills = 0;
			int paidBills = 0;
			int overdueBills = 0;

			for (PropertyFee fee : propertyFees) {
				totalAmount = totalAmount.add(fee.getAmount());
				totalBills++;

				if (fee.getPaymentStatus() == 1) { // 已缴费
					paidAmount = paidAmount.add(fee.getPaymentAmount());
					paidBills++;
				} else if (fee.getDueDate() != null && fee.getDueDate().isBefore(LocalDate.now())) {
					overdueBills++;
				}
			}

			statistics.setTotalAmount(totalAmount);
			statistics.setPaidAmount(paidAmount);
			statistics.setUnpaidAmount(totalAmount.subtract(paidAmount));
			statistics.setTotalBills(totalBills);
			statistics.setPaidBills(paidBills);
			statistics.setUnpaidBills(totalBills - paidBills);
			statistics.setOverdueBills(overdueBills);

			if (totalBills > 0) {
				statistics.setPaymentRate(paidBills * 100.0 / totalBills);
				statistics.setOverdueRate(overdueBills * 100.0 / totalBills);
			}

			// 月度统计转换为List<MonthlyStatistics>
			List<PropertyFeeStatisticsVO.MonthlyStatistics> monthlyList = new ArrayList<>();
			for (int month = 1; month <= 12; month++) {
				String monthKey = String.format("%04d-%02d", year, month);
				BigDecimal monthAmount = propertyFees.stream().filter(fee -> fee.getBillingPeriod().equals(monthKey))
						.map(PropertyFee::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
				PropertyFeeStatisticsVO.MonthlyStatistics ms = new PropertyFeeStatisticsVO.MonthlyStatistics();
				ms.setMonth(monthKey);
				ms.setAmount(monthAmount);
				ms.setBillCount(
						(int) propertyFees.stream().filter(fee -> fee.getBillingPeriod().equals(monthKey)).count());
				ms.setPercentage(totalAmount.compareTo(BigDecimal.ZERO) > 0
						? monthAmount.divide(totalAmount, 4, BigDecimal.ROUND_HALF_UP).doubleValue() * 100
						: 0.0);
				monthlyList.add(ms);
			}
			statistics.setMonthlyStatistics(monthlyList);

			return statistics;
		} catch (Exception e) {
			log.warn("获取物业费统计信息失败，社区ID: {}, 年份: {}", communityId, year, e);
			throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "获取统计信息失败: " + e.getMessage());
		}
	}

	// ========================= 维修工单管理 =========================

	// 删除多余的getRepairOrderPage、getRepairOrderStatistics(Integer year)等方法

	// ========================= 私有方法 =========================

	/**
	 * 转换为VO
	 */
	private PropertyFeeVO convertToVO(PropertyFee propertyFee) {
		PropertyFeeVO vo = new PropertyFeeVO();
		BeanUtils.copyProperties(propertyFee, vo);

		// 修复：手动处理dueDate字段转换（LocalDate -> LocalDate，无需转换）
		if (propertyFee.getDueDate() != null) {
			vo.setDueDate(propertyFee.getDueDate());
		}

		// 修复：手动处理面积字段映射
		if (propertyFee.getArea() != null) {
			vo.setArea(propertyFee.getArea());
		}

		// 修复：手动映射已支付金额字段（paidAmount -> paymentAmount）
		if (propertyFee.getPaidAmount() != null) {
			vo.setPaymentAmount(propertyFee.getPaidAmount());
		}

		// 计算剩余金额
		vo.calculateRemainingAmount();

		// 计算逾期天数
		vo.calculateOverdueDays();

		// 设置缴费状态名称
		vo.setPaymentStatusName(vo.getPaymentStatusName());

		// 设置费用类型名称
		vo.setFeeTypeName(vo.getFeeTypeName());

		// 设置缴费方式名称
		vo.setPaymentMethodName(vo.getPaymentMethodName());

		// 通过区域地址Feign接口获取详细地址信息
		try {
			if (propertyFee.getHouseholdId() != null) {
				AddressInfoDTO addressInfo = regionAddressFeignClient
						.getAddressByHouseholdId(propertyFee.getHouseholdId());
				if (addressInfo != null) {
					// 设置房户号
					vo.setRoomNumber(addressInfo.getRoomNumber());

					// 设置社区信息
					vo.setCommunityName(addressInfo.getCommunityName());

					// 设置楼栋信息
					vo.setBuildingName(addressInfo.getBuildingName());

					// 设置单元信息
					vo.setUnitName(addressInfo.getUnitName());

					// 设置房户地址（使用完整地址）
					vo.setHouseholdAddress(addressInfo.getFullAddress());
				}
			}
		} catch (Exception e) {
			log.warn("获取区域地址信息失败，物业费ID: {}, 房户ID: {}, 错误: {}", propertyFee.getId(), propertyFee.getHouseholdId(),
					e.getMessage());

			// 降级处理：使用基本信息
			vo.setCommunityName("未知社区");
			vo.setBuildingName("未知楼栋");
			vo.setUnitName("未知单元");
			vo.setRoomNumber("未知房号");
			vo.setHouseholdAddress("地址信息获取失败");
		}

		return vo;
	}

	/**
	 * 发送提醒通知
	 */
	private boolean sendReminderNotification(PropertyFee propertyFee, String remindType) {
		try {
			switch (remindType) {
			case "sms":
				// 调用短信服务
				log.info("发送短信催缴提醒，用户ID: {}, 账单ID: {}", propertyFee.getUserId(), propertyFee.getId());
				break;
			case "email":
				// 调用邮件服务
				log.info("发送邮件催缴提醒，用户ID: {}, 账单ID: {}", propertyFee.getUserId(), propertyFee.getId());
				break;
			case "app":
				// 调用APP推送服务
				log.info("发送APP推送催缴提醒，用户ID: {}, 账单ID: {}", propertyFee.getUserId(), propertyFee.getId());
				break;
			default:
				log.warn("不支持的提醒方式: {}", remindType);
				return false;
			}
			return true;
		} catch (Exception e) {
			log.warn("发送提醒通知失败", e);
			return false;
		}
	}

	/**
	 * 清除物业费缓存
	 * 注意：现在使用Spring Cache注解自动管理缓存，此方法保留用于兼容性
	 */
	@Override
	public void clearPropertyFeeCache(Long communityId) {
		// 缓存由Spring Cache注解自动管理，无需手动清理
		log.debug("物业费缓存由Spring Cache自动管理，社区ID: {}", communityId);
	}

	/**
	 * 清除用户物业费缓存
	 * 注意：现在使用Spring Cache注解自动管理缓存，此方法保留用于兼容性
	 */
	@Override
	public void clearUserPropertyFeeCache(Long userId) {
		// 缓存由Spring Cache注解自动管理，无需手动清理
		log.debug("用户物业费缓存由Spring Cache自动管理，用户ID: {}", userId);
	}

	@Override
	public List<RepairmanVO> getRepairmanList(Long communityId, Integer status) {
		try {
			log.info("获取维修人员列表，社区ID: {}, 状态: {}", communityId, status);

			// 数据权限校验
			DataScopeInfo dataScopeInfo = dataScopeService.getCurrentUserDataScope();
			List<Long> authorizedCommunityIds = dataScopeInfo.getCommunityIds();
			List<Long> authorizedPropertyCompanyIds = dataScopeInfo.getPropertyCompanyIds();

			// 如果指定了社区ID，检查权限
			if (communityId != null && !authorizedCommunityIds.contains(communityId)) {
				throw DataScopeException.communityPermissionDenied(communityId);
			}

			List<RepairmanVO> repairmanList;

			// 根据用户权限类型进行数据过滤
			if (dataScopeInfo.isSuperAdmin()) {
				// 超级管理员：显示所有维修人员
				log.info("超级管理员查询所有维修人员");
				repairmanList = repairmanMapper.selectAllRepairman(status);
			} else if (dataScopeInfo.isPropertyCompanyUser()) {
				// 物业公司用户：显示关联物业公司的维修人员
				// 根据架构设计，维修人员查询主要按物业公司ID过滤，不按社区ID过滤
				log.info("物业公司用户查询关联物业公司维修人员，物业公司IDs: {}，status：{}", authorizedPropertyCompanyIds, status);
				repairmanList = repairmanMapper.selectRepairmanList(null, // 不按社区ID过滤，避免查询条件过于严格
						authorizedPropertyCompanyIds, status);
			} else {
				// 普通用户：无权限访问维修人员列表
				log.info("普通用户无权限访问维修人员列表");
				repairmanList = new ArrayList<>();
			}

			log.info("获取维修人员列表成功，数量: {}", repairmanList.size());
			return repairmanList;
		} catch (Exception e) {
			log.warn("获取维修人员列表失败", e);
			throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), "获取维修人员列表失败: " + e.getMessage());
		}
	}

	/**
	 * 根据费用类型获取默认费用
	 * 
	 * @param feeType 费用类型
	 * @return 默认费用
	 */
	private BigDecimal getDefaultFeeByType(Integer feeType) {
		switch (feeType) {
		case 1:
			return new BigDecimal("50.00"); // 物业费默认50元
		case 2:
			return new BigDecimal("30.00"); // 水费默认30元
		case 3:
			return new BigDecimal("80.00"); // 电费默认80元
		case 4:
			return new BigDecimal("40.00"); // 燃气费默认40元
		case 5:
			return new BigDecimal("20.00"); // 卫生费默认20元
		default:
			return new BigDecimal("50.00"); // 默认50元
		}
	}

	/**
	 * 根据社区ID获取物业公司ID
	 * 
	 * @param communityId 社区ID
	 * @return 物业公司ID
	 */
	private Long getPropertyCompanyIdByCommunityId(Long communityId) {
		try {
			return propertyCompanyCommunityService.getPropertyCompanyIdByCommunityId(communityId);
		} catch (Exception e) {
			log.warn("获取社区对应的物业公司ID失败，社区ID: {}", communityId, e);
			return null;
		}
	}

	/**
	 * 根据物业公司ID和费用类型获取计费方式列表
	 * 
	 * @param propertyCompanyId 物业公司ID
	 * @param feeType           费用类型
	 * @return 计费方式列表
	 */
	private List<BillingMethod> getBillingMethodsByPropertyCompanyAndFeeTypeInternal(Long propertyCompanyId,
			String feeType) {
		try {
			// 调用计费方式服务获取计费方式列表
			List<BillingMethodVO> billingMethodVOs = billingMethodService
					.getBillingMethodsByPropertyCompanyAndFeeType(propertyCompanyId, feeType, null);

			// 将VO转换为实体对象
			List<BillingMethod> billingMethods = new ArrayList<>();
			for (BillingMethodVO vo : billingMethodVOs) {
				BillingMethod entity = new BillingMethod();
				entity.setId(vo.getId());
				entity.setPropertyCompanyId(vo.getPropertyCompanyId());
				entity.setFeeType(vo.getFeeType()); // 直接使用String类型
				entity.setBuildingTypeName(vo.getBuildingTypeName());
				entity.setMethodName(vo.getMethodName());
				entity.setMethodType(vo.getMethodType());
				entity.setUnitPrice(vo.getUnitPrice());
				entity.setFixedAmount(vo.getFixedAmount());
				entity.setTierConfig(vo.getTierConfig());
				entity.setDescription(vo.getDescription());
				entity.setStatus(vo.getStatus());
				entity.setSortOrder(vo.getSortOrder());
				billingMethods.add(entity);
			}

			return billingMethods;
		} catch (Exception e) {
			log.warn("获取计费方式列表失败，物业公司ID: {}, 费用类型: {}", propertyCompanyId, feeType, e);
			return Collections.emptyList();
		}
	}

	/**
	 * 根据楼栋建筑类型匹配计费方式
	 * 
	 * @param billingMethods 计费方式列表
	 * @param buildingType   楼栋建筑类型
	 * @param feeType        费用类型（用于验证）
	 * @return 匹配的计费方式
	 */
	private BillingMethod matchBillingMethodByBuildingType(List<BillingMethod> billingMethods, String buildingType,
			String feeType) {
		// 设置一个默认的先
		if (billingMethods.isEmpty()) {
			BillingMethod bm = new BillingMethod();
			bm.setFeeType(feeType);
			bm.setMethodName("默认物业费计费方式");
			bm.setMethodType(0);
			bm.setUnitPrice(BigDecimal.valueOf(2.0));
			billingMethods.add(bm);
		}

		// 优先匹配特定建筑类型的计费方式
		for (BillingMethod method : billingMethods) {
			if (method.getBuildingTypeName() != null && method.getBuildingTypeName().equals(buildingType)
					&& feeType.equals(method.getFeeType())) {
				return method;
			}
		}

		// 如果没有匹配到特定建筑类型，返回适用于所有建筑类型的计费方式
		for (BillingMethod method : billingMethods) {
			if ((method.getBuildingTypeName() == null || method.getBuildingTypeName().trim().isEmpty())
					&& feeType.equals(method.getFeeType())) {
				return method;
			}
		}

		return null;
	}

	/**
	 * 转换支付方式字符串为整数值
	 * 
	 * @param paymentMethod 支付方式字符串
	 * @return 支付方式整数值，如果不支持则返回null
	 */
	private Integer convertPaymentMethodToCode(String paymentMethod) {
		if (paymentMethod == null || paymentMethod.trim().isEmpty()) {
			return null;
		}

		PaymentMethodEnum methodEnum = PaymentMethodEnum.fromValue(paymentMethod.trim());
		return methodEnum != null ? methodEnum.getCode() : null;
	}
	
	// ========================= 生产环境优化工具方法 =========================
	
	/**
	 * 性能监控工具方法
	 * 记录方法执行时间和性能指标，用于生产环境监控
	 * 
	 * @param operation 操作描述
	 * @param startTime 开始时间
	 * @param result 执行结果
	 */
	private void logPerformanceMetrics(String operation, long startTime, Object result) {
		long responseTime = System.currentTimeMillis() - startTime;
		
		if (responseTime > PERFORMANCE_ERROR_THRESHOLD) {
			log.error("{}性能异常，耗时：{}ms，结果：{}", operation, responseTime, result);
		} else if (responseTime > PERFORMANCE_WARNING_THRESHOLD) {
			log.warn("{}性能警告，耗时：{}ms，结果：{}", operation, responseTime, result);
		} else {
			log.info("{}执行成功，耗时：{}ms，结果：{}", operation, responseTime, result);
		}
	}
	
	/**
	 * 参数验证工具方法
	 * 严格遵循Java后端SpringBoot代码开发规范中的参数验证要求
	 * 
	 * @param communityId 社区ID
	 * @throws IllegalArgumentException 参数无效时抛出异常
	 */
	private void validateCommunityId(Long communityId) {
		if (communityId == null) {
			log.error("社区ID不能为空");
			throw new IllegalArgumentException("社区ID不能为空");
		}
		if (communityId <= 0) {
			log.error("社区ID必须大于0，当前值：{}", communityId);
			throw new IllegalArgumentException("社区ID必须大于0");
		}
	}
	
	
	/**
	 * 参数验证工具方法
	 * 
	 * @param billId 账单ID
	 * @throws IllegalArgumentException 参数无效时抛出异常
	 */
	private void validateBillId(Long billId) {
		if (billId == null) {
			log.error("账单ID不能为空");
			throw new IllegalArgumentException("账单ID不能为空");
		}
		if (billId <= 0) {
			log.error("账单ID必须大于0，当前值：{}", billId);
			throw new IllegalArgumentException("账单ID必须大于0");
		}
	}
	
	/**
	 * 统一的异常处理工具方法
	 * 严格遵循Java后端SpringBoot代码开发规范中的异常处理要求
	 * 
	 * @param operation 操作描述
	 * @param e 异常对象
	 * @param startTime 开始时间
	 * @return 失败结果
	 */
	private <T> T handleException(String operation, Exception e, long startTime) {
		long responseTime = System.currentTimeMillis() - startTime;
		String errorMessage = String.format("%s失败，耗时：%dms", operation, responseTime);
		
		log.error(errorMessage, e);
		
		// 根据异常类型返回不同的错误信息
		if (e instanceof IllegalArgumentException) {
			throw new BusinessException(ResultCode.PARAM_ERROR.getCode(), "参数错误：" + e.getMessage());
		} else if (e instanceof BusinessException) {
			throw (BusinessException) e;
		} else {
			throw new BusinessException(ResultCode.OPERATION_FAILED.getCode(), operation + "失败：" + e.getMessage());
		}
	}
	
	/**
	 * 增强的缓存清除方法
	 * 支持多种缓存键模式的清除
	 * 
	 * @param communityId 社区ID
	 * @param userId 用户ID（可选）
	 */
	private void clearEnhancedPropertyFeeCache(Long communityId, Long userId) {
		// 缓存由Spring Cache注解自动管理，无需手动清理
		log.debug("增强物业费缓存由Spring Cache自动管理，社区ID: {}, 用户ID: {}", communityId, userId);
	}
	
	// ==================== 房户详情Tab页方法实现 ====================
	
	@Override
	@Cacheable(value = "property:household", key = "#householdId + ':' + #current + ':' + #size", unless = "#result == null || #result.getRecords().isEmpty()")
	public PageResult<PropertyFeeVO> getHouseholdPropertyFees(Long householdId, Integer current, Integer size) throws Exception {
		log.info("根据房户ID获取物业费列表，房户ID：{}，当前页：{}，每页大小：{}", householdId, current, size);
		
		try {
			// 根据房户ID查询物业费
			LambdaQueryWrapper<PropertyFee> wrapper = new LambdaQueryWrapper<>();
			wrapper.eq(PropertyFee::getHouseholdId, householdId);
			wrapper.eq(PropertyFee::getDeleted, 0);
			wrapper.orderByDesc(PropertyFee::getCreateTime);
			
			// 设置分页
			Page<PropertyFee> page = new Page<>(current, size);
			IPage<PropertyFee> propertyFeePage = baseMapper.selectPage(page, wrapper);
			
			// 转换为VO
			List<PropertyFeeVO> voList = new ArrayList<>();
			if (propertyFeePage.getRecords() != null && !propertyFeePage.getRecords().isEmpty()) {
				for (PropertyFee propertyFee : propertyFeePage.getRecords()) {
					PropertyFeeVO vo = new PropertyFeeVO();
					BeanUtils.copyProperties(propertyFee, vo);
					voList.add(vo);
				}
			}
			
			// 构建分页结果
			PageResult<PropertyFeeVO> result = new PageResult<>();
			result.setRecords(voList);
			result.setTotal(propertyFeePage.getTotal());
			result.setCurrent(current);
			result.setSize(size);
			
			log.info("根据房户ID获取物业费列表成功，房户ID：{}，物业费数量：{}", householdId, result.getTotal());
			return result;
			
		} catch (Exception e) {
			log.error("根据房户ID获取物业费列表失败，房户ID：{}", householdId, e);
			throw new Exception("根据房户ID获取物业费列表失败：" + e.getMessage());
		}
	}
	
}
